﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Rhino.Mocks;
using StockholmsStad.Data.Interfaces;
using StockholmsStad.Runtime.Serialization.DataContract;
using StockholmsStad.Runtime.Serialization.DataContract.Enums;

namespace StockholmsStad.Business.Test
{
    /// <summary>
    ///This is a test class for TicketBusinessTest and is intended
    ///to contain all TicketBusinessTest Unit Tests
    ///</summary>
    [TestClass()]
    public class TicketBusinessTest
    {
        private readonly User _user = new User() {Role = UserRole.Customer};
        private IDataContext _context;
        private MockRepository _mocks = new MockRepository();

        #region Additional test attributes

        // 
        //You can use the following additional attributes as you write your tests:
        //
        //Use ClassInitialize to run code before running the first test in the class
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //Use ClassCleanup to run code after all tests in a class have run
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}

        //Use TestInitialize to run code before running each test
        [TestInitialize()]
        public void MyTestInitialize()
        {
            _mocks = new MockRepository();
        }

        //Use TestCleanup to run code after each test has run
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}
        //

        #endregion

        private TicketBusiness GetTarget(IAgentFactory agentFactory)
        {
            var target = new TicketBusiness(_user);
            target.AgentFactory = agentFactory;
            _context = _mocks.DynamicMock<IDataContext>();
            IContextFactory contextFactory = new MockContextFactory(_context);
            //target.ContextFactory = contextFactory;
            return target;
        }

        /// <summary>
        ///A test for UpdateTicket
        ///</summary>
        [TestMethod()]
        public void UpdateTicketTest()
        {
            var agentFactory = new MockAgentFactory();
            ITicketAgent ticketAgent = _mocks.StrictMock<ITicketAgent>();
            agentFactory.TicketAgent = ticketAgent;
            TicketBusiness target = GetTarget(agentFactory);
            // Object
            const int ticketId = 34;
            Couple couple = new Couple() {Person1 = new Person() {Email = "test"}};
            Ceremony ceremony = new Ceremony();
            // Expect
            Expect.Call(() => ticketAgent.UpdateTicket(_context, ticketId, couple, ceremony, couple.Person1.Email));
            // Replay
            _mocks.ReplayAll();
            target.UpdateTicket(couple, ceremony, ticketId);
            _mocks.VerifyAll();
        }

        /// <summary>
        ///A test for UpdateTicket
        ///</summary>
        [TestMethod()]
        public void UpdateTicketTest2()
        {
            var agentFactory = new MockAgentFactory();
            ITicketAgent ticketAgent = _mocks.StrictMock<ITicketAgent>();
            agentFactory.TicketAgent = ticketAgent;
            TicketBusiness target = GetTarget(agentFactory);
            // Object
            const int ticketId = 34;
            Couple couple = new Couple()
                                {
                                    ContactPerson = new ContactPerson() {Email = "test"},
                                    Person1 = new Person() {Email = "not user email"}
                                };
            Ceremony ceremony = new Ceremony();
            // Expect
            Expect.Call(() => ticketAgent.UpdateTicket(_context, ticketId, couple, ceremony, couple.ContactPerson.Email));
            // Replay
            _mocks.ReplayAll();
            target.UpdateTicket(couple, ceremony, ticketId);
            _mocks.VerifyAll();
        }

        /// <summary>
        ///A test for GetTickets
        ///</summary>
        [TestMethod()]
        public void GetTicketsTest()
        {
            var agentFactory = new MockAgentFactory();
            ITicketAgent ticketAgent = _mocks.StrictMock<ITicketAgent>();
            agentFactory.TicketAgent = ticketAgent;
            TicketBusiness target = GetTarget(agentFactory);
            // Object
            var tickets = new List<CouplesSummaryItem>()
                                   {
                                       new CouplesSummaryItem() {TicketId = 1},
                                       new CouplesSummaryItem() {TicketId = 2},
                                       new CouplesSummaryItem() {TicketId = 3},
                                   };
            // Expect
            Expect.Call(ticketAgent.GetTickets(_context, "", "", TicketStatusType.Started)).Return(tickets);
            // Replay
            _mocks.ReplayAll();
            List<CouplesSummaryItem> actual = target.GetTickets("", "", TicketStatusType.Started) as List<CouplesSummaryItem>;
            _mocks.VerifyAll();
            Assert.AreEqual(tickets.Count, actual.Count);
            for (int i = 0; i < actual.Count; i++)
            {
                Assert.AreEqual(tickets[i].TicketId, actual[i].TicketId);
            }
        }

        /// <summary>
        ///A test for GetTicket
        ///</summary>
        [TestMethod()]
        public void GetTicketTest()
        {
            var agentFactory = new MockAgentFactory();
            ITicketAgent ticketAgent = _mocks.StrictMock<ITicketAgent>();
            agentFactory.TicketAgent = ticketAgent;
            TicketBusiness target = GetTarget(agentFactory);
            // Object
            Ticket ticket = new Ticket() {TicketId = 1};
            // Expect
            Expect.Call(ticketAgent.GetTicket(_context, 122)).Return(ticket);
            // Replay
            _mocks.ReplayAll();
            Ticket actual = target.GetTicket(122);
            _mocks.VerifyAll();
            Assert.AreEqual(ticket.TicketId, actual.TicketId);
        }

        /// <summary>
        ///A test for DeleteTicket
        ///</summary>
        [TestMethod()]
        [ExpectedException(typeof (NotImplementedException))]
        public void DeleteTicketTest()
        {
            const User user = null;
            TicketBusiness target = new TicketBusiness(user);
            const int ticketId = 0;
            //target.DeleteTicket(ticketId);
        }

        /// <summary>
        ///A test for CreateTicket. No contact
        ///</summary>
        [TestMethod()]
        public void CreateTicketTest()
        {
            var agentFactory = new MockAgentFactory();
            ITicketAgent ticketAgent = _mocks.StrictMock<ITicketAgent>();
            agentFactory.TicketAgent = ticketAgent;
            IUserAgent userAgent = _mocks.StrictMock<IUserAgent>();
            agentFactory.UserAgent = userAgent;
            TicketBusiness target = GetTarget(agentFactory);
            // Object
            const string username = "uname";
            Couple couple = new Couple()
                                {
                                    Person1 = new Person()
                                                  {
                                                      Email = username,
                                                      FirstNames = "first",
                                                      LastName = "last"
                                                  }
                                };
            Ceremony ceremony = new Ceremony();
            const string password = "password";
            // Expect
            Expect.Call(userAgent.CreatePassword(_context)).Return(password);
            Expect.Call(ticketAgent.CreateTicket(_context, couple, ceremony)).Return(123);
            //Expect.Call(() => userAgent.SendRegistrationMail(_context, couple.Person1, username, password));
            //Expect.Call(() => ticketAgent.InsertHistory(_context, 123, HistoryType.NewRegistration, password, username));
            // Replay
            _mocks.ReplayAll();
            int ticketId = target.CreateTicket(couple, ceremony);
            Assert.AreEqual(123, ticketId);
            _mocks.VerifyAll();
        }

        /// <summary>
        ///A test for CreateTicket. With contact
        ///</summary>
        [TestMethod()]
        public void CreateTicketTest2()
        {
            var agentFactory = new MockAgentFactory();
            ITicketAgent ticketAgent = _mocks.StrictMock<ITicketAgent>();
            agentFactory.TicketAgent = ticketAgent;
            IUserAgent userAgent = _mocks.StrictMock<IUserAgent>();
            agentFactory.UserAgent = userAgent;
            TicketBusiness target = GetTarget(agentFactory);
            // Object
            const string username = "uname";
            Couple couple = new Couple()
                                {
                                    ContactPerson = new ContactPerson()
                                                        {
                                                            Email = username,
                                                            FirstNames = "first",
                                                            LastName = "last"
                                                        }
                                };
            Ceremony ceremony = new Ceremony();
            const string password = "password";
            // Expect
            Expect.Call(userAgent.CreatePassword(_context)).Return(password);
            Expect.Call(ticketAgent.CreateTicket(_context, couple, ceremony)).Return(123);
            //Expect.Call(() => userAgent.SendRegistrationMail(_context, couple.ContactPerson, username, password));
            // Replay
            _mocks.ReplayAll();
            int ticketId = target.CreateTicket(couple, ceremony);
            Assert.AreEqual(123, ticketId);
            _mocks.VerifyAll();
        }

        /// <summary>
        ///A test for TicketBusiness Constructor
        ///</summary>
        [TestMethod()]
        public void TicketBusinessConstructorTest()
        {
            const User user = null;
            TicketBusiness target = new TicketBusiness(user);
            Assert.IsNotNull(target);
        }
    }
}